Abstract
Questo documento rappresenta un’approfondita analisi statistica nel campo del basket professionistico, con un focus specifico sulle prestazioni delle squadre NBA. Utilizzando metodi statistici avanzati, si esplorano diverse metriche chiave per comprendere meglio le dinamiche del gioco e i fattori che influenzano il successo delle squadre.df$games == 82). Questo criterio
assicura l’uniformità e la comparabilità dei dati analizzati.In questo report, ci siamo concentrati sull’elaborazione di un modello lineare predittivo per determinare il numero di vittorie in funzione dei rimbalzi annuali effettuati dalle squadre nella NBA. Il modello si applica esclusivamente a squadre che hanno disputato almeno 82 partite per stagione, considerando un arco temporale che va dal 1976 al 2011.
L’approccio del modello lineare si basa sull’adozione di coefficienti accuratamente selezionati, mirati a massimizzare la significatività e l’aderenza alla nostra interpretazione dell’impatto di specifiche variabili sulle vittorie. Questi coefficienti sono stati scelti in modo da riflettere al meglio la nostra concezione di quali fattori influenzino maggiormente il successo delle squadre.
Ulteriori informazioni riguardanti l’esecuzione del programma e l’utilizzo della funzione predittiva sono fornite nei paragrafi successivi, dove viene anche descritto il processo di sviluppo e validazione del modello.
TODO: aggiungere descrizione per ogni grafico
filepath <- here("0_Materiale", "basketball_teams.txt")
dataset <- read.delim(filepath)
# str(dataset)
FIRST <- 1976 # primo anno del range da considerare per lo studio
LAST <- 2011 # ultimo anno del range da considerare per lo studio
df <- dataset [dataset$lgID=="NBA" & dataset$year >= FIRST & dataset$year <= LAST & dataset$games==82,]
df$reb <- df$o_reb + df$d_reb
# summary(df)
Nel nostro dataframe sono incluse variabili specifiche per analizzare in dettaglio il ruolo dei rimbalzi nel basket. Ecco una descrizione degli acronimi utilizzati:
## [1] "Percentage non-zero o_oreb: 100"
## [1] "Percentage non-zero o_dreb: 100"
## [1] "Percentage non-zero o_reb: 100"
## [1] "Percentage non-zero d_oreb: 100"
## [1] "Percentage non-zero d_dreb: 100"
## [1] "Percentage non-zero d_reb: 100"
Il test Anderson-Darling è un test statistico non parametrico,
utilizzato per verificare l’ipotesi che un campione di dati provenga da
una particolare distribuzione, in questo caso, la distribuzione normale.
È particolarmente sensibile alle deviazioni nella coda della
distribuzione.
- Range: 0 a \(+\infty\)
- Interpretazione: Valori più bassi indicano una
maggiore aderenza alla distribuzione normale. Si confronta il valore di
test con valori critici specifici per determinare se rifiutare l’ipotesi
di normalità.
ad.test(df$reb)
##
## Anderson-Darling normality test
##
## data: df$reb
## A = 3.6997, p-value = 3.1e-09
Con un livello di significatività (\(\alpha\)) di 0.01 e un p-value molto piccolo (3.1e-09) ottenuto dal test di normalità di Anderson-Darling per i dati della variabile df$reb, puoi concludere che hai sufficiente evidenza statistica per respingere lipotesi nulla che i dati seguono una distribuzione normale.Con il tuo livello di significatività del 0.01 e il p-value molto piccolo (3.1e-09), il p-value è inferiore al livello di significatività, quindi respingeresti lipotesi nulla. Questo suggerisce che i dati nella variabile df$reb non seguono una distribuzione normale al livello di significatività del 0.01. In termini più pratici, hai abbastanza evidenza statistica per concludere che la variabile df$reb non segue una distribuzione normale basandoti sui risultati del test di Anderson-Darling.
Il test Kolmogorov-Smirnov (K-S) è un metodo non parametrico
utilizzato per determinare se un campione di dati segue una specifica
distribuzione, in questo caso, la distribuzione normale. È ampiamente
impiegato per la sua generalità e la facilità di implementazione.
- Range: 0 a 1
- Interpretazione: Valori più bassi indicano una
maggiore somiglianza alla distribuzione normale. Un valore di test
significativamente grande porta al rifiuto dell’ipotesi di
normalità.
ks.test(df$reb, "pnorm")
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: df$reb
## D = 1, p-value < 2.2e-16
## alternative hypothesis: two-sided
Il risultato che hai ottenuto riguarda il test di Kolmogorov-Smirnov a campione singolo sui dati contenuti nella variabile df$reb. Il test KS confronta la distribuzione empirica dei tuoi dati con una distribuzione teorica (spesso una distribuzione uniforme). In breve, il risultato suggerisce che i tuoi dati non seguono la distribuzione teorica presunta, e cè un elevata probabilità che la differenza osservata sia statisticamente significativa.
Il test Shapiro-Wilk è un metodo statistico non parametrico
utilizzato specificatamente per testare la normalità di un campione di
dati. È noto per la sua affidabilità e precisione, soprattutto in
campioni di dimensioni ridotte.
- Range: 0 a 1
- Interpretazione: Valori più vicini a 1 suggeriscono
una maggiore aderenza alla distribuzione normale. Valori
significativamente bassi indicano la deviazione dalla normalità.
ks.test(df$reb, "pnorm")
##
## Asymptotic one-sample Kolmogorov-Smirnov test
##
## data: df$reb
## D = 1, p-value < 2.2e-16
## alternative hypothesis: two-sided
In sintesi, il risultato del test di Shapiro-Francia indica che i tuoi dati nella variabile df$reb non seguono una distribuzione normale. Questo è supportato dal valore basso del p-value, il quale suggerisce che la differenza tra la distribuzione dei tuoi dati e una distribuzione normale è statisticamente significativa.
Abbiamo creato un modello lineare per esplorare come i rimbalzi influenzano le vittorie in NBA. L’idea è semplice: capire se squadre che rimbalzano meglio vincono di più. Il modello analizza diversi tipi di rimbalzi (offensivi, difensivi) e come questi si traducono in successo sul campo.
Le formule che usiamo si concentrano su diversi aspetti dei rimbalzi, come recuperare la palla dopo un tiro sbagliato o proteggere il canestro. Ogni formula ci dà un’idea di come le squadre gestiscono e sfruttano i rimbalzi durante le partite. L’obiettivo è vedere quale impatto hanno questi fattori sulle vittorie.
\(\text{Formula1} = \frac{\text{Rimbalzi offensivi in attacco}}{\text{Tiri sbagliati su azione}}\)
\(\text{Formula2} = \frac{\text{Rimbalzi difensivi in difesa presi}}{\text{Tiri sbagliati su azione degli avversari}}\)
\(\text{Formula3} = \frac{\text{Palle riprese in attacco} + 1.5 \times \text{Palle riprese in difesa}}{\text{Palle perse in attacco} + 2 \times \text{Rimbalzi subiti in difesa}}\)
\(\text{Formula4} = (\text{Palle riprese in attacco - Palle perse in attacco}) + 1.5*(\text{Palle riprese in difesa - Palle perse in difesa})\)
\(\text{Formula5} = \frac{(\frac{\text{Rimbalzi subiti in difesa}}{\text{Palle perse in difesa}})}{(\frac{\text{Rimbalzi subiti in attacco}}{\text{Palle perse in attacco}})}\)
\(\text{Formula6} = (\text{Rimbalzi ottenuti in attacco} + \text{Rimbalzi ottenuti in difesa}) - (\text{Rimbalzi subiti in difesa} - \text{Rimbalzi subiti in attacco})^2\)
\(\text{Formula7} = (\text{Efficienza nel Rimbalzo Offensivo} + \text{Competenza nel Rimbalzo Difensivo})^2\)
\(\text{Formula8} = \frac{\text{Rimbalzi ottenuti in attacco}}{\text{Totale rimbalzi in attacco}}\)
\(\text{Formula9} = \left(\frac{\text{Rimbalzi ottenuti in attacco}}{\text{Rimbalzi subiti in attacco}}\right)^2\)
\(\text{Formula10} = \left(\frac{\text{Rimbalzi ottenuti in difesa}}{\text{Rimbalzi subiti in difesa}}\right)^2\)
Legenda significato acronimi:
df$f1 <- (df$o_oreb)/(df$o_fga-df$o_fgm)
df$f2 <- (df$d_dreb)/(df$d_fga-df$d_fgm)
df$f3 <- (df$o_oreb + 1.5 * df$d_dreb)/(df$o_dreb + 2 * df$d_oreb)
df$f4 <- (df$o_oreb - df$o_dreb) + 1.5 * (df$d_dreb - df$d_oreb)
df$f5 <- (df$d_oreb / df$d_to) / (df$o_dreb / df$o_to)
df$f6 <- (df$o_oreb + df$d_dreb) - (df$d_oreb - df$o_dreb)^2
df$f7 <- (df$f1 + df$f2)^2
df$f8 <- (df$o_oreb)/(df$o_reb)
df$f9 <- ((df$o_oreb)/(df$o_dreb))^2
df$f10 <- ((df$d_dreb)/(df$d_oreb))^2
num_rows_to_sample <- round(0.7 * nrow(df))
sample_indices <- sample(seq_len(nrow(df)), size = num_rows_to_sample, replace = FALSE)
df = subset(df, select = c("f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "won"))
train <- df[sample_indices, ]
test <- df[-sample_indices, ]
linMod <- lm(won ~ f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10, data = train)
summary (linMod)
##
## Call:
## lm(formula = won ~ f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 +
## f10, data = train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -10.7241 -3.0795 -0.0215 3.1463 14.2833
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 1.045e+03 9.406e+01 11.113 < 2e-16 ***
## f1 -7.057e+02 1.617e+02 -4.363 1.52e-05 ***
## f2 -1.042e+03 1.721e+02 -6.052 2.57e-09 ***
## f3 -4.460e+02 3.732e+01 -11.953 < 2e-16 ***
## f4 7.663e-02 8.278e-03 9.257 < 2e-16 ***
## f5 -1.926e+02 4.792e+00 -40.188 < 2e-16 ***
## f6 1.222e-05 1.487e-06 8.216 1.39e-15 ***
## f7 4.645e+02 8.661e+01 5.363 1.18e-07 ***
## f8 -1.492e+02 7.312e+01 -2.040 0.0418 *
## f9 1.001e+01 2.324e+01 0.431 0.6668
## f10 5.409e+00 9.644e-01 5.609 3.16e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.697 on 578 degrees of freedom
## Multiple R-squared: 0.8661, Adjusted R-squared: 0.8638
## F-statistic: 373.9 on 10 and 578 DF, p-value: < 2.2e-16
TODO: Aggiungere presentazione grafici
La normalizzazione dei dati è una pratica fondamentale nell’elaborazione di modelli statistici, specialmente nei modelli lineari. Questo processo è volto a standardizzare la scala delle variabili, rendendo più agevole il confronto tra di esse e migliorando l’efficienza dell’algoritmo di regressione. In particolare, la normalizzazione è cruciale quando le variabili hanno scale molto diverse, poiché ciò potrebbe influenzare negativamente la precisione del modello.
Nel codice R seguente, abbiamo normalizzato le variabili del nostro
dataframe ‘df’, utilizzando la funzione scale. Questo
assicura che ciascuna variabile contribuisca in modo equo al modello,
permettendo una più accurata interpretazione dei coefficienti della
regressione lineare.
# Normalizziamo le covariate
train$f1_z <- scale(train$f1)
train$f2_z <- scale(train$f2)
train$f3_z <- scale(train$f3)
train$f4_z <- scale(train$f4)
train$f5_z <- scale(train$f5)
train$f6_z <- scale(train$f6)
train$f7_z <- scale(train$f7)
train$f8_z <- scale(train$f8)
train$f9_z <- scale(train$f9)
train$f10_z <- scale(train$f10)
# Normalizzo i dati di test
test$f1_z <- scale(test$f1)
test$f2_z <- scale(test$f2)
test$f3_z <- scale(test$f3)
test$f4_z <- scale(test$f4)
test$f5_z <- scale(test$f5)
test$f6_z <- scale(test$f6)
test$f7_z <- scale(test$f7)
test$f8_z <- scale(test$f8)
test$f9_z <- scale(test$f9)
test$f10_z <- scale(test$f10)
linModNormalized <- lm(won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z + f7_z + f8_z + f9_z + f10_z, data = train)
summary(linModNormalized)
##
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z +
## f7_z + f8_z + f9_z + f10_z, data = train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -10.7241 -3.0795 -0.0215 3.1463 14.2833
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 40.8353 0.1935 210.990 < 2e-16 ***
## f1_z -22.4942 5.1555 -4.363 1.52e-05 ***
## f2_z -49.8705 8.2398 -6.052 2.57e-09 ***
## f3_z -28.8464 2.4134 -11.953 < 2e-16 ***
## f4_z 20.5851 2.2237 9.257 < 2e-16 ***
## f5_z -13.5662 0.3376 -40.188 < 2e-16 ***
## f6_z 6.3671 0.7750 8.216 1.39e-15 ***
## f7_z 38.2339 7.1291 5.363 1.18e-07 ***
## f8_z -4.8538 2.3794 -2.040 0.0418 *
## f9_z 0.6192 1.4373 0.431 0.6668
## f10_z 7.7583 1.3832 5.609 3.16e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.697 on 578 degrees of freedom
## Multiple R-squared: 0.8661, Adjusted R-squared: 0.8638
## F-statistic: 373.9 on 10 and 578 DF, p-value: < 2.2e-16
Il processo di test di un modello lineare è cruciale per assicurare la sua affidabilità e accuratezza. Questa fase prevede la valutazione di vari aspetti del modello, come l’adattamento dei dati, la normalità dei residui, l’omoschedasticità e la multicollinearità. Ognuno di questi test fornisce un’indicazione su come il modello si adatta ai dati e su eventuali problemi che potrebbero influenzarne le prestazioni.
Per una comprensione immediata del modello, è utile visualizzare il
riepilogo tramite summary(linModNormalized). Questo
fornisce dettagli sui coefficienti, la significatività statistica e
altre metriche chiave.
summary (linModNormalized)
##
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z +
## f7_z + f8_z + f9_z + f10_z, data = train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -10.7241 -3.0795 -0.0215 3.1463 14.2833
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 40.8353 0.1935 210.990 < 2e-16 ***
## f1_z -22.4942 5.1555 -4.363 1.52e-05 ***
## f2_z -49.8705 8.2398 -6.052 2.57e-09 ***
## f3_z -28.8464 2.4134 -11.953 < 2e-16 ***
## f4_z 20.5851 2.2237 9.257 < 2e-16 ***
## f5_z -13.5662 0.3376 -40.188 < 2e-16 ***
## f6_z 6.3671 0.7750 8.216 1.39e-15 ***
## f7_z 38.2339 7.1291 5.363 1.18e-07 ***
## f8_z -4.8538 2.3794 -2.040 0.0418 *
## f9_z 0.6192 1.4373 0.431 0.6668
## f10_z 7.7583 1.3832 5.609 3.16e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.697 on 578 degrees of freedom
## Multiple R-squared: 0.8661, Adjusted R-squared: 0.8638
## F-statistic: 373.9 on 10 and 578 DF, p-value: < 2.2e-16
Il test R-quadrato misura la proporzione della varianza totale della
variabile dipendente che viene spiegata dal modello di regressione. Un
R-quadrato elevato indica che una grande parte della varianza nella
variabile dipendente può essere spiegata dalle variabili indipendenti
nel modello.
- Range: 0 a 1
- Interpretazione: 0 indica nessuna spiegazione della
varianza da parte del modello. 1 indica una spiegazione completa della
varianza da parte del modello.
summary_linModNormalized <- summary(linModNormalized)
r_squared <- summary_linModNormalized$r.squared
cat("R-squared:", r_squared, "\n")
## R-squared: 0.8661242
Il R-quadrato adattato modifica il R-quadrato per tenere conto del
numero di predittori nel modello. È più affidabile per i modelli con
molteplici variabili indipendenti, poiché penalizza la complessità
aggiuntiva, fornendo una misura più realistica della bontà di
adattamento.
- Range: Può essere negativo, ma generalmente 0 a
1
- Interpretazione: Valori più vicini a 1 indicano una
migliore spiegazione della varianza, considerando il numero di
predittori.
n <- length(train$o_reb)
k <- length(linModNormalized$coefficients) - 1
adjusted_r_squared <- 1 - ((1 - r_squared) * (n - 1) / (n - k - 1))
cat("R-quadro adattato:", adjusted_r_squared, "\n")
## R-quadro adattato: 0.9878295
Il test di Shapiro-Wilk sui residui è utilizzato per valutare la
normalità dei residui in un modello di regressione lineare. La normalità
dei residui è un’assunzione critica in molti test statistici. Se i
residui non seguono una distribuzione normale, le inferenze sulle stime
dei parametri potrebbero essere invalide.
- Range: 0 a 1
- Interpretazione: Valori più vicini a 1 suggeriscono
una maggiore probabilità che i residui seguano una distribuzione
normale.
shapiro.test(residuals(linModNormalized))
##
## Shapiro-Wilk normality test
##
## data: residuals(linModNormalized)
## W = 0.99466, p-value = 0.03788
Il Breusch-Pagan test verifica l’assunzione di omoschedasticità
(varianza costante) dei residui in un modello di regressione. La
presenza di eteroschedasticità (varianza non costante) nei residui può
portare a stime inefficaci e test statistici non affidabili.
- Range: 0 a \(+\infty\)
- Interpretazione: Valori più alti indicano una
maggiore probabilità di eteroschedasticità. Si confronta il valore del
test con un valore critico (ad es., da una distribuzione chi-quadrato)
per determinare la significatività.
bptest(linModNormalized)
##
## studentized Breusch-Pagan test
##
## data: linModNormalized
## BP = 9.4948, df = 10, p-value = 0.4859
Il test di multicollinearità verifica se esiste una correlazione
elevata tra le variabili indipendenti in un modello di regressione
lineare. La multicollinearità può causare problemi nella stima dei
coefficienti del modello, rendendo difficili l’interpretazione e la
significatività statistica delle variabili indipendenti. Strumenti
comuni per rilevarla includono il fattore di inflazione della varianza
(VIF) e l’indice di tolleranza.
- Range del VIF: 1 a \(+\infty\)
- Interpretazione: 1 indica assenza di
multicollinearità. Valori superiori a 5 o 10 sono spesso considerati
indicatori di multicollinearità significativa.
car::vif(linModNormalized)
## f1_z f2_z f3_z f4_z f5_z f6_z
## 708.369671 1809.461926 155.224696 131.783848 3.036989 16.007068
## f7_z f8_z f9_z f10_z
## 1354.527134 150.890046 55.054117 50.988184
Questa sezione si dedica all’identificazione e rimozione degli outliers nel nostro modello lineare normalizzato. Gli outliers possono influenzare notevolmente l’accuratezza e l’affidabilità delle previsioni del modello.
Il primo passo è identificare gli outliers. Utilizziamo un grafico di influenza per visualizzare i punti che hanno un impatto maggiore sul modello.
influencePlot(linModNormalized,5)
Successivamente, calcoliamo i residui del modello e identifichiamo come outliers quei punti la cui distanza dalla media è superiore a un valore soglia, in questo caso due deviazioni standard.
residui <- residuals(linModNormalized)
soglia_outlier <- 2
outliers <- which(abs(residui) > soglia_outlier*sd(residui))
outliers
## 936 1139 624 900 1224 470 891 1128 945 1301 1161 715 940 837 1306 957
## 6 42 68 148 208 246 259 261 272 278 322 328 338 379 390 403
## 440 541 769 652 1214 1107 516 638 799
## 407 431 433 450 459 497 513 558 588
Dopo aver identificato gli outliers, procediamo con la loro rimozione dal dataset di allenamento.
if(length(outliers) != 0)
{
train_1 <- train[-outliers,]
}else
{
# questo è il caso in cui non sono presenti outliers
train_1 <- train
}
Confrontiamo i summary del modello prima e dopo la rimozione degli outliers per valutare l’impatto di questa operazione sulle prestazioni del modello.
##
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z +
## f7_z + f8_z + f9_z + f10_z, data = train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -10.7241 -3.0795 -0.0215 3.1463 14.2833
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 40.8353 0.1935 210.990 < 2e-16 ***
## f1_z -22.4942 5.1555 -4.363 1.52e-05 ***
## f2_z -49.8705 8.2398 -6.052 2.57e-09 ***
## f3_z -28.8464 2.4134 -11.953 < 2e-16 ***
## f4_z 20.5851 2.2237 9.257 < 2e-16 ***
## f5_z -13.5662 0.3376 -40.188 < 2e-16 ***
## f6_z 6.3671 0.7750 8.216 1.39e-15 ***
## f7_z 38.2339 7.1291 5.363 1.18e-07 ***
## f8_z -4.8538 2.3794 -2.040 0.0418 *
## f9_z 0.6192 1.4373 0.431 0.6668
## f10_z 7.7583 1.3832 5.609 3.16e-08 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.697 on 578 degrees of freedom
## Multiple R-squared: 0.8661, Adjusted R-squared: 0.8638
## F-statistic: 373.9 on 10 and 578 DF, p-value: < 2.2e-16
##
## Call:
## lm(formula = won ~ f1_z + f2_z + f3_z + f4_z + f5_z + f6_z +
## f7_z + f8_z + f9_z + f10_z, data = train_1)
##
## Residuals:
## Min 1Q Median 3Q Max
## -9.3228 -2.8178 0.2679 2.9899 9.6268
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 40.67594 0.17569 231.522 < 2e-16 ***
## f1_z -27.26020 5.05459 -5.393 1.03e-07 ***
## f2_z -59.36823 8.05538 -7.370 6.25e-13 ***
## f3_z -32.77490 2.28073 -14.370 < 2e-16 ***
## f4_z 24.78018 2.13800 11.590 < 2e-16 ***
## f5_z -13.67790 0.30700 -44.553 < 2e-16 ***
## f6_z 7.38585 0.72587 10.175 < 2e-16 ***
## f7_z 45.81535 6.98331 6.561 1.23e-10 ***
## f8_z -5.31091 2.16956 -2.448 0.0147 *
## f9_z -0.07144 1.29346 -0.055 0.9560
## f10_z 9.39195 1.27760 7.351 7.11e-13 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 4.169 on 553 degrees of freedom
## Multiple R-squared: 0.8935, Adjusted R-squared: 0.8916
## F-statistic: 464.1 on 10 and 553 DF, p-value: < 2.2e-16
E il rispettivo grafico di influenza
# Crea il grafico di influenza
influence_plot <- influencePlot(linModNormalized_1, id = 5, main = "Influence Plot")
## Warning in applyDefaults(id, defaults = list(method = "noteworthy", n = 2, :
## unnamed id arguments, will be ignored
influence_plot
Entrambi i modelli mostrano prestazioni simili, spiegando circa l’84% della varianza nella variabile dipendente “won”. Tuttavia, la rimozione degli outliers ha leggermente migliorato i risultati. Dato che la differenza tra i due modelli è minima (<0.5%), e quindi trascurabile, abbiamo optato per mantenere il modello che include gli outliers.
Questo blocco di codice utilizza la funzione
ols_plot_resid_lev per visualizzare la relazione tra i
residui e il leverage per entrambi i modelli lineari (prima e dopo la
rimozione degli outliers). Questa visualizzazione aiuta a identificare
ulteriori punti influenti o pattern nei residui che potrebbero
influenzare le prestazioni del modello.
Qui prepariamo un modello di regressione LASSO. Il LASSO è utilizzato per la selezione di variabili e la regolarizzazione, aiutando a prevenire l’overfitting e migliorare la generalizzazione del modello.
# METODO DI REGRESSIONE LASSO
# define response variable
y <- train_1$won
# define matrix of predictor variables
x <- data.matrix(train_1[, c("f1_z", "f2_z", "f3_z", "f4_z", "f5_z", "f6_z", "f7_z", "f8_z", "f9_z", "f10_z")])
# perform k-fold cross-validation to find optimal lambda value
cv_model <- cv.glmnet(x, y, alpha = 1)
# find optimal lambda value that minimizes test MSE
best_lambda <- cv_model$lambda.min
best_lambda
## [1] 0.003396238
# Fitting the model with the best lambda
best_model <- glmnet(x, y, alpha = 1, lambda = best_lambda)
# Output coefficients and summary
coef(best_model)
## 11 x 1 sparse Matrix of class "dgCMatrix"
## s0
## (Intercept) 40.655114
## f1_z -10.424709
## f2_z -31.719585
## f3_z -29.182514
## f4_z 20.880471
## f5_z -13.618352
## f6_z 6.295922
## f7_z 21.904583
## f8_z -5.713989
## f9_z 1.434278
## f10_z 7.516939
Effettuiamo le previsioni utilizzando sia il modello LASSO che quello lineare sui dati di test.
# PREDICT
# Lasso Prediction
new = data.matrix(test[,c("f1_z","f2_z","f3_z","f4_z","f5_z", "f6_z", "f7_z", "f8_z", "f9_z", "f10_z")])
prevLasso = predict(best_model, s = best_lambda, newx = new)
# Linear Model Prediction
new = subset(test, select = c("f1_z","f2_z","f3_z","f4_z","f5_z", "f6_z", "f7_z", "f8_z", "f9_z", "f10_z"))
prevLM = predict(linModNormalized_1, newdata = test)
Confrontiamo le prestazioni di entrambi i modelli (LASSO e lineare) attraverso diverse metriche.
# RMS Lasso
sqrt(mean((test$won - prevLasso)^2))
## [1] 4.699991
# RMS LM
sqrt(mean((test$won - prevLM)^2))
## [1] 4.797089
# Previsioni binarie
prev <- ifelse(prevLasso > 0.5, "1", "0")
prev <- as.factor(as.vector(prev))
# Confusion Matrix: previsioni vs valore reale
table(prev, test$won)
##
## prev 11 13 14 15 17 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
## 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 1 0 1 1 2 1 2 2 3 5 1 5 4 3 1 6 6 4 11 1 6 4 4 9 7 4
##
## prev 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 62 63 64
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 1 7 6 15 11 7 12 10 5 5 3 7 10 5 5 4 8 7 5 7 4 4 3 3 2 1
##
## prev 66 67
## 0 0 0
## 1 1 1
Calcoliamo diverse metriche di valutazione come l’accuratezza (accuracy), la precisione (precision), la sensibilità (sensitivity), l’F-score e la specificità (specificity). Queste metriche forniscono una valutazione complessiva dell’efficacia del modello.
Ecco come interpretarle:
cm <- table(prev, test$won)
# Metriche di Valutazione
accuracy <- sum(cm[1], cm[4]) / sum(cm[1:4])
precision <- cm[4] / sum(cm[4], cm[2])
sensitivity <- cm[4] / sum(cm[4], cm[3])
fscore <- (2 * (sensitivity * precision)) / (sensitivity + precision)
specificity <- cm[1] / sum(cm[1], cm[2])
## [1] "Accuratezza: 1.000000"
## [1] "Precisione: 1.000000"
## [1] "Sensibilità: 1.000000"
## [1] "F-score: 1.000000"
## [1] "Specificità: 1.000000"